package com.yinhe.music.yhmusic.downmusic;

/**
 * Created by wm on 2016/4/12.
 */

import android.content.Context;
import android.util.Log;
import android.widget.Toast;

import com.yinhe.music.yhmusic.constants.BasicConfig;
import com.yinhe.music.yhmusic.db.bean.DownloadMusicEntity;
import com.yinhe.music.yhmusic.log.MLog;
import com.yinhe.music.yhmusic.model.Music;
import com.yinhe.music.yhmusic.utils.ScheduledTask;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;

import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;


/**
 * Created by dzc on 15/11/21.
 */
public class DownloadTask implements Runnable {

    private DownloadMusicEntity dbEntity;
    private OkHttpClient client;
    private Context mContext;

    private long totalSize = 0;
    private long completedSize = 0;         //  Download section has been completed

    private RandomAccessFile file;
    private int UPDATE_SIZE = 50 * 1024;    // The database is updated once every 50k

    private Music music;
    private String TAG = "DownloadTask";

    public DownloadTaskListener mListener;

    public DownloadTask(Context context, DownloadTaskListener listener) {
        mListener = listener;
        mContext = context.getApplicationContext();
    }

    public void setDBEntity(DownloadMusicEntity dbEntity) {
        this.dbEntity = dbEntity;
        music = new Music(dbEntity);
    }


    public String getFileName(){
        if (music == null){
            return "";
        }
        if (music.getFileName() != null){
            return music.getFileName();
        }
        if (music.getSongName() != null) {
            return music.getSongName();
        }
        return "";
    }


    @Override
    public void run() {
        dbEntity.setDownloadStatus(DownloadStatus.DOWNLOAD_STATUS_PREPARE);

        completedSize = 0;
        totalSize = 0;

        onPrepare();

        InputStream inputStream = null;
        BufferedInputStream bis = null;
        try {
            file = new RandomAccessFile(getFilePath(), "rwd");
            if (file.length() < completedSize) {
                completedSize = file.length();
            }
            long fileLength = file.length();

            if (fileLength != 0 && totalSize == fileLength) {
                dbEntity.setDownloadStatus(DownloadStatus.DOWNLOAD_STATUS_COMPLETED);
                totalSize = completedSize = fileLength;
                Toast.makeText(mContext, music.getFileName() + "已经下载完成", Toast.LENGTH_SHORT).show();

                onCompleted();
                return;
            } else {
                completedSize = 0;
                totalSize = 0;
            }
            dbEntity.setDownloadStatus(DownloadStatus.DOWNLOAD_STATUS_START);
            onStart();
            Request request = new Request.Builder()
                    .url(music.getUrl())
                    .header("RANGE", "bytes=" + completedSize + "-")//  Http value set breakpoints RANGE
                    .addHeader("Referer", music.getUrl())
                    .build();
            file.seek(completedSize);
            Response response = client.newCall(request).execute();
            ResponseBody responseBody = response.body();
            if (responseBody != null) {
                dbEntity.setDownloadStatus(DownloadStatus.DOWNLOAD_STATUS_DOWNLOADING);
                if (totalSize <= 0) {
                    totalSize = responseBody.contentLength();
                }
                inputStream = responseBody.byteStream();
                bis = new BufferedInputStream(inputStream);
                byte[] buffer = new byte[4 * 1024];
                int length = 0;
                int buffOffset = 0;

                if( dbEntity.getDownloadStatus() != DownloadStatus.DOWNLOAD_STATUS_CANCEL && dbEntity.getDownloadStatus() != DownloadStatus.DOWNLOAD_STATUS_PAUSE){
                    downloadingflag = true;
                    startDownloading();
                }
                while ((length = bis.read(buffer)) > 0 && dbEntity.getDownloadStatus() != DownloadStatus.DOWNLOAD_STATUS_CANCEL && dbEntity.getDownloadStatus() != DownloadStatus.DOWNLOAD_STATUS_PAUSE) {
                    file.write(buffer, 0, length);
                    completedSize += length;
                    buffOffset += length;
                    if (buffOffset >= UPDATE_SIZE) {
                        buffOffset = 0;
                    }
                }
                downloadingflag = false;
                //这两句根据需要自行选择是否注释，注释掉的话由于少了数据库的读取，速度会快一点，但同时如果在下载过程程序崩溃的话，程序不会保存最新的下载进度
                onDownloading();
            }
        } catch (FileNotFoundException e) {
            dbEntity.setDownloadStatus(DownloadStatus.DOWNLOAD_STATUS_ERROR);
            onError(DownloadTaskListener.DOWNLOAD_ERROR_FILE_NOT_FOUND);
            e.printStackTrace();
            return;
        } catch (IOException e) {
            dbEntity.setDownloadStatus(DownloadStatus.DOWNLOAD_STATUS_ERROR);
            onError(DownloadTaskListener.DOWNLOAD_ERROR_IO_ERROR);
            return;
        } catch(Exception e){
            e.printStackTrace();
        }
        finally {
            // String  nP = fileName.substring(0, path.length() - 5);
            dbEntity.setFileName(music.getFileName());
            if (bis != null) {
                try {
                    bis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (file != null) {
                try {
                    file.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        if (totalSize == completedSize && totalSize != 0) {
            dbEntity.setDownloadStatus(DownloadStatus.DOWNLOAD_STATUS_COMPLETED);
        }

        switch (dbEntity.getDownloadStatus()) {
            case DownloadStatus.DOWNLOAD_STATUS_COMPLETED:
                onCompleted();
                break;
            case DownloadStatus.DOWNLOAD_STATUS_PAUSE:
                onPause();
                break;
            case DownloadStatus.DOWNLOAD_STATUS_CANCEL:
                onCancel();
                break;
        }
    }

    public long getId() {
        return dbEntity.getDownloadId();
    }

    public long getTotalSize() {
        return totalSize;
    }

    public long getCompletedSize() {
        return completedSize;
    }

    int getDownloadStatus() {
        return dbEntity.getDownloadStatus();
    }

    void setDownloadStatus(int downloadStatus) {
        dbEntity.setDownloadStatus(downloadStatus);
    }

    DownloadMusicEntity getDbEntity() {
        return dbEntity;
    }

    void setHttpClient(OkHttpClient client) {
        this.client = client;
    }

    public void cancel() {
        setDownloadStatus(DownloadStatus.DOWNLOAD_STATUS_CANCEL);
        File temp = new File(BasicConfig.getInstance().getMusicDownLoadDir()
                + File.separator+music.getFileName());
        if (temp.exists()) {
            temp.delete();
        }
    }

    public void pause() {
        setDownloadStatus(DownloadStatus.DOWNLOAD_STATUS_PAUSE);
    }

    private void onPrepare() {
        if (mListener == null) {
            return;
        }
        mListener.onPrepare(this);
    }

    private void onStart() {
        if (mListener == null) {
            return;
        }
        mListener.onStart(this);
    }

    private void onDownloading() {
        if (mListener == null) {
            return;
        }
        mListener.onDownloading(this);
    }

    private void onCompleted() {
        if (mListener == null) {
            return;
        }
        mListener.onCompleted(this);
    }

    private void onPause() {
        if (mListener == null) {
            return;
        }
        mListener.onPause(this);
    }

    private void onCancel() {
        if (mListener == null) {
            return;
        }
        mListener.onCancel(this);
    }

    private void onError(int errorCode) {
        if (mListener == null) {
            return;
        }
        mListener.onError(this, errorCode);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (!(o instanceof DownloadTask)) {
            return false;
        }
        return music.getUrl().equals(((DownloadTask) o).music.getUrl());
    }

    @Override
    public String toString() {
        return "DownloadTask{" +
                "totalsize = " + totalSize +
                " completesize = " + completedSize +
                " id='" + music.getId() + '\'' +
                ", url='" + music.getUrl() + '\'' +
                ", fileName='" + music.getFileName() + '\'' +
                '}';
    }

    public String getFilePath(){
        return BasicConfig.getInstance().getMusicDownLoadDir() +File.separator+ music.getFileName();
    }

    private boolean downloadingflag = false;

    Runnable OnDownloadTask = new Runnable() {
        @Override
        public void run() {
            if(downloadingflag){
                onDownloading();
                ScheduledTask.getInstance().removeCallbacks(OnDownloadTask);
                ScheduledTask.getInstance().scheduledDelayed(OnDownloadTask,500);
            }
        }
    };

    private void startDownloading(){
        ScheduledTask.getInstance().removeCallbacks(OnDownloadTask);
        ScheduledTask.getInstance().scheduledDelayed(OnDownloadTask,500);
    }
}
